﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NBusiness.ESharp.Compiler;
using NBusiness.ESharp.Testing.Mocks;
using NBusiness.CodeDom.Compiler;
using NBusiness.CodeDom;
using NBusiness.ESharp.Testing.Properties;
using NBusiness.Data.Rules;
using NBusiness.CodeDom.Services;

namespace NBusiness.ESharp.Testing
{
    /// <summary>
    /// Summary description for CustomValidationFrameworkTests
    /// </summary>
    [TestClass]
    public class CustomRuleFrameworkTests
    {
        public CustomRuleFrameworkTests()
        {
            //
            // TODO: Add constructor logic here
            //
        }

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        [TestMethod]
        public void TestCustomValidationRuleFramework()
        {
            ESharpProvider provider = new ESharpProvider();
            MockBuildErrorService errorService = new MockBuildErrorService();
            MockTypeFinder typeFinderService = new MockTypeFinder();
            provider.SetService(typeof(IBuildErrorService), errorService);

            EntityRoot root = provider.GetParser().ParseFiles(
                new EntityFile ("Rules.CustomFramework.Validation.es", Resources.Rules_CustomFramework_Validation ));

            Assert.AreEqual(0, errorService.Errors.Count);
            Assert.AreEqual(1, root.Families.Count);
            Assert.IsNotNull(root.Families["Rules"]);
            Assert.AreEqual(1, root.Families["Rules"].Entities.Count);
            Assert.AreEqual("Test", root.Families["Rules"].Entities[0].Name);
            Assert.AreEqual(2, root.Families["Rules"].Entities[0].Fields.Count);
            Assert.AreEqual(1, root.Families["Rules"].Entities[0].Rules.Count);
            Assert.IsInstanceOfType(root.Families["Rules"].Entities[0].Rules[0], typeof(EntityValidation));
            Assert.AreSame(
                root.Families["Rules"].Entities[0].Fields[1],
                (root.Families["Rules"].Entities[0].Rules[0] as EntityValidation).Validatable);

            EntityValidation validationRule = root.Families["Rules"].Entities[0].Rules[0] as EntityValidation;
        }

        [TestMethod]
        public void TestCustomAccessFramework()
        {
            ESharpProvider provider = new ESharpProvider();
            MockBuildErrorService errorService = new MockBuildErrorService();
            MockTypeFinder typeFinderService = new MockTypeFinder();
            provider.SetService(typeof(IBuildErrorService), errorService);

            EntityRoot root = provider.GetParser().ParseFiles(
                new EntityFile ("Rules.CustomFramework.Access.es", Resources.Rules_CustomFramework_Access ));

            Assert.AreEqual(0, errorService.Errors.Count);
            Assert.AreEqual(1, root.Families.Count);
            Assert.IsNotNull(root.Families["Rules"]);
            Assert.AreEqual(1, root.Families["Rules"].Entities.Count);
            Assert.AreEqual("Test", root.Families["Rules"].Entities[0].Name);
            Assert.AreEqual(2, root.Families["Rules"].Entities[0].Fields.Count);
            Assert.AreEqual(1, root.Families["Rules"].Entities[0].Rules.Count);
            Assert.IsInstanceOfType(root.Families["Rules"].Entities[0].Rules[0], typeof(EntityAccess));
            Assert.AreSame(
                root.Families["Rules"].Entities[0].Fields[1],
                (root.Families["Rules"].Entities[0].Rules[0] as EntityAccess).Accessible);

            EntityAccess accessRule = root.Families["Rules"].Entities[0].Rules[0] as EntityAccess;
        }

        [TestMethod]
        public void TestCustomAuthorizationFramework()
        {
            ESharpProvider provider = new ESharpProvider();
            MockBuildErrorService errorService = new MockBuildErrorService();
            MockTypeFinder typeFinderService = new MockTypeFinder();
            provider.SetService(typeof(IBuildErrorService), errorService);

            EntityRoot root = provider.GetParser().ParseFiles(
                new EntityFile("Rules.CustomFramework.Authorization.es", Resources.Rules_CustomFramework_Authorization));

            Assert.AreEqual(0, errorService.Errors.Count);
            Assert.AreEqual(1, root.Families.Count);
            Assert.IsNotNull(root.Families["Rules"]);
            Assert.AreEqual(1, root.Families["Rules"].Entities.Count);
            Assert.AreEqual("Test", root.Families["Rules"].Entities[0].Name);
            Assert.AreEqual(2, root.Families["Rules"].Entities[0].Fields.Count);
            Assert.AreEqual(1, root.Families["Rules"].Entities[0].Rules.Count);
            Assert.IsInstanceOfType(root.Families["Rules"].Entities[0].Rules[0], typeof(EntityAuthorization));

            EntityAuthorization authorizationRule = root.Families["Rules"].Entities[0].Rules[0] as EntityAuthorization;
        }
    }
}
